package controllers

import java.io.{File, FileFilter}
import java.nio.file.Files

import javax.inject.Inject
import play.api.mvc.{AbstractController, ControllerComponents}
import tool._
import dao._
import models.Tables._
import org.joda.time.DateTime
import play.api.libs.json.Json
import utils.Utils

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.reflect.internal.util.FileUtils
import implicits.Implicits._


/**
 * Created by Administrator on 2019/8/7
 */
class AdminController @Inject()(cc: ControllerComponents, formTool: FormTool, accountDao: AccountDao,
                                userDao: UserDao)(
                                 implicit val configDao: ConfigDao,
                                 implicit val posSiteDao: PosSiteDao
                               ) extends
  AbstractController(cc) {

  def userManageBefore = Action { implicit request =>
    Ok(views.html.admin.userManage())
  }

  def posSiteBefore = Action { implicit request =>
    Ok(views.html.admin.posSite())
  }

  def logout = Action { implicit request =>
    Redirect(routes.AppController.loginBefore()).flashing("info" -> "退出登录成功!").removingFromSession("admin")
  }

  def getAllUser = Action.async { implicit request =>
    userDao.selectAll.map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(Json.toJson(array))
    }
  }

  def userNameCheck = Action.async { implicit request =>
    val data = formTool.userNameForm.bindFromRequest.get
    userDao.selectByName(data.name).zip(accountDao.selectById1).map { case (optionUser, admin) =>
      optionUser match {
        case Some(y) => Ok(Json.obj("valid" -> false))
        case None =>
          val valid = if (data.name == admin.account) false else true
          Ok(Json.obj("valid" -> valid))
      }
    }
  }

  def deleteUserById = Action.async { implicit request =>
    val data = formTool.idForm.bindFromRequest().get
    userDao.deleteById(data.id).map { x =>
      Ok("success")
    }
  }

  def addUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    val row = UserRow(0, data.name, data.password, new DateTime())
    userDao.insert(row).map { userId =>
      Ok(Json.toJson("success!"))
    }
  }

  def getUserById = Action.async { implicit request =>
    val data = formTool.idForm.bindFromRequest().get
    userDao.selectById(data.id).map { x =>
      Ok(Utils.getJsonByT(x))
    }
  }

  def updateUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    userDao.selectByNameSome(data.name).flatMap { dbUser =>
      val row = dbUser.copy(password = data.password)
      userDao.update(row).map { x =>
        Ok("success")
      }
    }
  }

  def changePasswordBefore = Action { implicit request =>
    Ok(views.html.admin.changePassword())
  }

  def changePassword = Action.async { implicit request =>
    val data = formTool.changePasswordForm.bindFromRequest().get
    accountDao.selectById1.flatMap { x =>
      if (data.password == x.password) {
        val row = AccountRow(x.id, x.account, data.newPassword)
        accountDao.update(row).map { y =>
          Redirect(routes.AppController.loginBefore()).flashing("info" -> "密码修改成功!").withNewSession
        }
      } else {
        Future.successful(Redirect(routes.AdminController.changePasswordBefore()).flashing("info" -> "密码错误!"))
      }
    }
  }

  def gzPathSetBefore = Action { implicit request =>
    Ok(views.html.admin.gzPathSet())
  }

  def getTreeNodes = Action { implicit request =>
    val dir = new File(Utils.execFuture(configDao.selectRootPath).value)

    def loop(acc: List[Map[String, String]], files: List[File]): List[Map[String, String]] = {
      files match {
        case Nil => acc
        case x :: xs if x.isDirectory =>
          val nodes = if (x.getParentFile != null) {
            x.getParentFile.myListFiles.map { y =>
              Map("id" -> y.getAbsolutePath, "pId" -> y.getParentFile.getAbsolutePath, "name" -> y.getName,
                "icon" -> "/assets/images/baidu_folder.png", "isParent" -> y.isParent.toString)
            }
          } else List[Map[String, String]]()
          val list = if (x.getParentFile != null) List(x.getParentFile) else List[File]()
          loop(nodes ::: acc, xs ::: list)
        case x :: xs =>
          loop(acc, xs)
      }
    }

    val f = configDao.selectGzPath
    val gzPath = Utils.execFuture(f)
    val gzDir = new File(gzPath)
    val dbNodes = loop(List[Map[String, String]](), List(gzDir)).filter(!_.isEmpty).
      filter { x =>
        x("pId") != dir.getAbsolutePath
      }

    val nodes = dir.myListFiles.map { x =>
      if (x.isDirectory) {
        Map("id" -> x.getAbsolutePath, "pId" -> x.getParentFile.getAbsolutePath, "name" -> x.getName,
          "icon" -> "/assets/images/baidu_folder.png", "isParent" -> x.isParent.toString)
      } else Map[String, String]()
    }.filter(!_.isEmpty)

    Ok(Json.toJson(nodes ::: dbNodes))
  }

  def getChildrenNodes = Action { implicit request =>
    val rootDir = Tool.getRootDir
    val dir = FormTool.nodeForm.bindFromRequest().fold(e => rootDir, s => new File(s.id))
    val nodes = dir.myListFiles.map { x =>
      if (x.isDirectory) {
        Map("id" -> x.getAbsolutePath, "pId" -> x.getParentFile.getAbsolutePath, "name" -> x.getName,
          "icon" -> "/assets/images/baidu_folder.png", "isParent" -> x.isParent.toString)
      } else Map[String, String]()
    }.filter(!_.isEmpty)
    Ok(Json.toJson(nodes))
  }

  def updateGzPath = Action.async { implicit request =>
    val data = FormTool.adminSetForm.bindFromRequest().get
    configDao.selectGzPath.flatMap { dbGzPath =>
      if (dbGzPath == data.gzPath) {
        Utils.result2Future(Ok(Json.obj("operate" -> "none")))
      } else {
        configDao.updateGzPath(data.gzPath).map { x =>
          Ok(Json.obj("operate" -> "update"))
        }
      }
    }
  }

  def getFiles = Action { implicit request =>
    val data = FormTool.adminSetForm.bindFromRequest().get
    val dir = new File(data.gzPath)
    val maps = dir.listFiles().filter(_.isFile).map { file =>
      Map("id" -> file.getAbsolutePath, "name" -> file.getName, "isParent" -> "false")
    }
    Ok(Json.toJson(maps))
  }


  def gzPathCheck = Action { implicit request =>
    val data = FormTool.adminSetForm.bindFromRequest.get
    val file = new File(data.gzPath)
    if (file.exists() && file.isDirectory) {
      Ok(Json.obj("valid" -> true))
    } else Ok(Json.obj("valid" -> false))
  }

  def getGzPath = Action.async { implicit request =>
    configDao.selectGzPath.map { gzPath =>
      Ok(Json.obj("gzPath" -> gzPath))
    }
  }

  def updatePosStrSite = Action.async { implicit request =>
    val strData = formTool.strForm.bindFromRequest().get
    val sexData = FormTool.sexForm.bindFromRequest().get
    val strMap = strData.strSiteNames.zip(strData.strSiteDatas).map { case (siteName, siteDataOp) =>
      (siteName, siteDataOp)
    }.toList.toSeqMap
    val strRow = PosSiteRow(sexData.sex, "str", Json.toJson(strMap).toString())
    posSiteDao.update(strRow).map { x =>
      Ok("success!")
    }
  }

  def updatePosSnpSite = Action.async { implicit request =>
    val snpData = formTool.snpForm.bindFromRequest().get
    val sexData = FormTool.sexForm.bindFromRequest().get
    val snpMap = snpData.snpSiteNames.zip(snpData.snpSiteDatas).map { case (siteName, siteDataOp) =>
      (siteName, siteDataOp)
    }.toList.toSeqMap
    val strRow = PosSiteRow(sexData.sex, "snp", Json.toJson(snpMap).toString())
    posSiteDao.update(strRow).map { x =>
      Ok("success!")
    }
  }

  def getPosSiteInfo = Action.async { implicit request =>
    posSiteDao.selectAll.map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }


}
